package com.zjhn.ds.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zjhn.ds.common.BizResult;
import com.zjhn.ds.common.exception.BizException;
import com.zjhn.ds.domain.dto.mt.*;
import com.zjhn.ds.domain.entity.erp.*;
import com.zjhn.ds.domain.entity.jlw.*;
import com.zjhn.ds.mapper.*;
import com.zjhn.ds.param.CompleteTaskParam;
import com.zjhn.ds.param.FinishTaskParam;
import com.zjhn.ds.param.StationMonitorParam;
import com.zjhn.ds.service.AppStationMonitorService;
import com.zjhn.ds.service.StationMonitorService;
import com.zjhn.ds.utils.CommonUtil;
import com.zjhn.ds.utils.base.DateUtil;
import lombok.extern.slf4j.Slf4j;
import nonapi.io.github.classgraph.json.Id;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.Collator;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @BelongsProject: ds_jlw
 * @BelongsPackage: com.zjhn.ds.service.impl
 * @Author: sxt
 * @CreateTime: 2023-10-05  13:55
 * @Description:
 * @Version: 1.0
 */
@Slf4j
@Service
public class StationMonitorServiceImpl implements StationMonitorService {

    @Resource
    private CommonUtil commonUtil;

    @Resource
    private GroupSpinnerMapper groupSpinnerMapper;

    @Resource
    private GroupStationMapper groupStationMapper;

    @Resource
    private GroupMapper groupMapper;

    @Resource
    private StationMapper stationMapper;

    @Resource
    private AssignTaskMapper assignTaskMapper;

    @Resource
    private SwipeCardInfoMapper swipeCardInfoMapper;

    @Resource
    private AppStationMonitorService appStationMonitorService;

    @Resource
    private ProTaskMapper proTaskMapper;

    @Resource
    private ProTaskDetailMapper proTaskDetailMapper;

    @Resource
    private TradeOrderDetailMapper tradeOrderDetailMapper;

    @Resource
    private ReportRecordMapper reportRecordMapper;

    @Resource
    private BindInfoMapper bindInfoMapper;

    @Resource
    private MesBookjobMapper mesBookjobMapper;

    @Resource
    private ProBoxMapper proBoxMapper;

    @Resource
    private PreListMapper preListMapper;


    /**
     * 机台监控页面数据
     *
     * @param param
     * @return
     */
    @Override
    public BizResult<StationMonitorDto> stationMonitor(StationMonitorParam param) {
        List<StationMonitorDto.StationInfo> list = new ArrayList<>();
        StationMonitorDto res = StationMonitorDto.builder()
                .runnerQty(0)
                .standByQty(0)
                .closeQty(0)
                .faultQty(0)
                .blQty(0)
                .dysQty(0)
                .ysQty(0)
                .taskOverQty(0)
                .taskWarnQty(0)
                .remainOneDayQty(0)
                .remainTwoDayQty(0)
                .list(list)
                .build();

        List<GroupStation> groupStations = groupStationMapper.selectList(new QueryWrapper<GroupStation>().eq("group_id", param.getGroupId()));
        if (groupStations.size() == 0)
            return BizResult.success(res);

        Map<String, Integer> taskStatusMap = new HashMap<>();
        Set<String> stationIds = groupStations.stream().map(GroupStation::getStationId).collect(Collectors.toSet());
        Map<String, AssignTask> assignTaskMap = new HashMap<>();
        // 获取机台当前刷卡信息
        List<SwipeCardInfo> swipeCardInfos = swipeCardInfoMapper.selectList(new QueryWrapper<SwipeCardInfo>().in("station_id", stationIds));
        Map<String, SwipeCardInfo> swipeCardInfoMap = new HashMap<>();
        if (swipeCardInfos.size() > 0) {
            swipeCardInfoMap = swipeCardInfos.stream().collect(Collectors.toMap(SwipeCardInfo::getStationId, c -> c));
            List<String> assignTaskIds = swipeCardInfos.stream().map(SwipeCardInfo::getAssignTaskId).collect(Collectors.toList());

            Set<String> proTaskDetailIds = new HashSet<>();
            Map<String, ProTaskDetail> proTaskDetailMap = new HashMap<>();
            if (assignTaskIds.size() > 0) {
                // 获取刷卡对应的派工任务
                List<AssignTask> assignTasks = assignTaskMapper.selectBatchIds(assignTaskIds);
                assignTaskMap = assignTasks.stream().collect(Collectors.toMap(AssignTask::getStationId, c -> c));

                // 进度
                proTaskDetailIds.addAll(assignTasks.stream().map(AssignTask::getTaskDetailId).collect(Collectors.toSet()));
                List<ProTaskDetail> proTaskDetails = proTaskDetailMapper.selectBatchIds(proTaskDetailIds);
                proTaskDetailMap.putAll(proTaskDetails.stream().collect(Collectors.toMap(ProTaskDetail::getId, c -> c)));

            }

            if (proTaskDetailIds.size() > 0) {
                List<AssignTask> all = assignTaskMapper.selectList(new QueryWrapper<AssignTask>().in("task_detail_id", proTaskDetailIds));
                Map<String, List<AssignTask>> assignTaskGroup = all.stream().collect(Collectors.groupingBy(AssignTask::getTaskDetailId));
                for (String taskDetailId : assignTaskGroup.keySet()) {
                    ProTaskDetail proTaskDetail = proTaskDetailMap.get(taskDetailId);
                    if (proTaskDetail == null)
                        return BizResult.fail("对应生产明细不存在");

                    List<AssignTask> collect = assignTaskGroup.get(taskDetailId);
                    BigDecimal taskFinishQty = BigDecimal.ZERO;
                    if (collect.size() > 0)
                        taskFinishQty = collect.stream().map(AssignTask::getCompleteQty).reduce(BigDecimal.ZERO, BigDecimal::add);

                    int taskStatus = 1;
                    if (proTaskDetail.getWarnQty() != null) {
                        if (taskFinishQty.compareTo(BigDecimal.valueOf(proTaskDetail.getNumber())) >= 0)
                            taskStatus = 3;
                        else if (taskFinishQty.compareTo(proTaskDetail.getWarnQty()) >= 0)
                            taskStatus = 2;
                    }else {
                        if (taskFinishQty.compareTo(BigDecimal.valueOf(proTaskDetail.getNumber())) >= 0)
                            taskStatus = 3;
                    }
                    taskStatusMap.put(taskDetailId, taskStatus);
                }
            }
        }

        // 获取agv状态
        Map<String, Integer> preListMap = new HashMap<>();
        List<PreList> preLists = preListMapper.selectList(new QueryWrapper<PreList>()
                .in("MasterId", stationIds).ne("CarryFlowStatus", 2));
        for (PreList preList : preLists)
            preListMap.put(preList.getMasterId(), preList.getCarryFlowStatus());

        // 获取绑定关系
        Map<String,String> bindInfoMap = new HashMap<>();
        List<BindInfo> bindInfos = bindInfoMapper.selectList(new QueryWrapper<BindInfo>().in("station_id", stationIds));
        if (bindInfos.size() > 0)
            bindInfoMap.putAll(bindInfos.stream().collect(Collectors.toMap(BindInfo::getStationId, BindInfo::getEquipmentId)));

        Integer runnerCount = 0;
        Integer standByQty = 0;
        Integer closeQty = 0;
        Integer faultQty = 0;
        Integer blQty = 0;
        Integer dysQty = 0;
        Integer ysQty = 0;
        Integer taskOverQty = 0;
        Integer taskWarnQty = 0;
        Integer remainOneDayQty = 0;
        Integer remainTwoDayQty = 0;
        for (GroupStation groupStation : groupStations) {
            SwipeCardInfo swipeCardInfo = swipeCardInfoMap.get(groupStation.getStationId());
            if (swipeCardInfo != null) {
                if (StringUtils.isNotBlank(param.getStyleCode())) {
                    if (StringUtils.isBlank(swipeCardInfo.getStyleCode())) {
                        continue;
                    }
                    if (!swipeCardInfo.getStyleCode().contains(param.getStyleCode()))
                        continue;
                }
            }else if (StringUtils.isNotBlank(param.getStyleCode()))
                continue;


            String brand = null;
            String equipmentId = bindInfoMap.get(groupStation.getStationId());
            if (StringUtils.isNotBlank(equipmentId))
                brand = commonUtil.getEquipmentById(equipmentId).getBrand();

            Integer status = commonUtil.getStationStatus(groupStation.getStationId());
            if (status == 0) closeQty++;
            else if (status == 1) runnerCount++;
            else if (status == 2) standByQty++;
            else if (status == 3) faultQty++;

            Integer agvStatus = preListMap.get(groupStation.getStationId());
            if (agvStatus != null) {
                // 2-备料中, 3-待运输, 4-运输中
                if (agvStatus == 2)
                    blQty++;
                else if (agvStatus == 3)
                    dysQty++;
                else if (agvStatus == 4)
                    ysQty++;
            }

            StationMonitorDto.StationInfo build = StationMonitorDto.StationInfo.builder()
                    .stationId(groupStation.getStationId())
                    .stationCode(commonUtil.getStationById(groupStation.getStationId()).getStationCode())
                    .stationName(commonUtil.getStationById(groupStation.getStationId()).getStationName())
                    .status(status)
                    .remainDay(0)
                    .brand(brand)
                    .agvStatus(agvStatus)

                    .build();


            if (swipeCardInfo != null) {
                build.setStyleCode(swipeCardInfo.getStyleCode());
                build.setColorMain(swipeCardInfo.getColorMain());
                build.setSize(swipeCardInfo.getSize());

                // 计算剩余时间
                AssignTask assignTask = assignTaskMap.get(swipeCardInfo.getStationId());
                if (assignTask != null) {
                    build.setCompleteQty(assignTask.getCompleteQty());
                    build.setAssignQty(assignTask.getAssignQty());

                    Date date = DateUtil.dateAddMinute(assignTask.getBeginTime(), assignTask.getRequire());
                    if (date.compareTo(new Date()) > 0) {
                        Integer intervalDays = DateUtil.intervalDays(date, new Date());
                        build.setRemainDay(intervalDays);

                        if (intervalDays == 1)
                            remainOneDayQty++;
                        else if (intervalDays == 2)
                            remainTwoDayQty++;
                    }
                }
                Integer taskStatus = taskStatusMap.get(swipeCardInfo.getProTaskDetailId());
                if (taskStatus != null && taskStatus  == 2)
                    taskWarnQty++;
                else if (taskStatus != null && taskStatus  == 3)
                    taskOverQty++;
                build.setTaskStatus(taskStatus);
            }

            list.add(build);
        }

        res.setRunnerQty(runnerCount);
        res.setStandByQty(standByQty);
        res.setCloseQty(closeQty);
        res.setFaultQty(faultQty);
        res.setBlQty(blQty);
        res.setDysQty(dysQty);
        res.setYsQty(ysQty);
        res.setTaskOverQty(taskOverQty);
        res.setTaskWarnQty(taskWarnQty);
        res.setRemainOneDayQty(remainOneDayQty);
        res.setRemainTwoDayQty(remainTwoDayQty);

        // 排序
        if (param.getOrder() == 1)
            // 工位编号
            list.sort(Comparator.comparing(c -> c.getStationCode().replace("-", "")));
        else if (param.getOrder() == 2)
            // 机台状态
            list.sort(Comparator.comparing(StationMonitorDto.StationInfo::getStatus));
        else
            // 剩余时间
            list.sort(Comparator.comparing(StationMonitorDto.StationInfo::getRemainDay));

        return BizResult.success(res);
    }

    /**
     * pad获取工位当前刷卡任务
     *
     * @param stationId
     * @return
     */
    @Override
    public BizResult<CurrentTaskDto> currentTask(String stationId) {
        return appStationMonitorService.currentTask(stationId);
    }

    /**
     * pad任务完成
     *
     * @param param
     * @return
     */
    @Override
    public BizResult<?> finishTask(FinishTaskParam param) {
        return appStationMonitorService.finishTask(param);
    }

    /**
     * pad获取工位排队任务
     *
     * @param stationId
     * @return
     */
    @Override
    public BizResult<List<QueueTaskDto>> queueTask(String stationId) {
        return appStationMonitorService.queueTask(stationId);
    }

    /**
     * pad获取工位已完成任务
     *
     * @param param
     * @return
     */
    @Override
    public BizResult<List<CompleteTaskDto>> completeTask(CompleteTaskParam param) {
        List<CompleteTaskDto> res = new ArrayList<>();
        List<AssignTask> assignTasks = assignTaskMapper.selectList(
                new QueryWrapper<AssignTask>()
                        .eq("station_id", param.getStationId())
                        .eq("task_status", 2)
                        .orderByAsc("create_time"));

        if (assignTasks.size() > 0) {
            // 生产单
            Set<String> taskIds = assignTasks.stream().map(AssignTask::getTaskId).collect(Collectors.toSet());
            List<ProTask> proTasks = proTaskMapper.selectBatchIds(taskIds);
            Map<String, ProTask> proTaskMap = proTasks.stream().collect(Collectors.toMap(ProTask::getId, c -> c));

            Set<String> taskDetailIds = assignTasks.stream().map(AssignTask::getTaskDetailId).collect(Collectors.toSet());
            // 生产明细
            List<ProTaskDetail> proTaskDetails = proTaskDetailMapper.selectBatchIds(taskDetailIds);
            Map<String, ProTaskDetail> proTaskDetailMap = proTaskDetails.stream().collect(Collectors.toMap(ProTaskDetail::getId, c -> c));

            // 交易单明细
            Set<String> orderDetailIds = proTaskDetails.stream().map(ProTaskDetail::getTradeOrderDetailId).collect(Collectors.toSet());
            List<TradeOrderDetail> tradeOrderDetails = tradeOrderDetailMapper.selectBatchIds(orderDetailIds);
            Map<String, TradeOrderDetail> orderDetailMap = tradeOrderDetails.stream().collect(Collectors.toMap(TradeOrderDetail::getId, c -> c));

            for (AssignTask assignTask : assignTasks) {
                ProTask proTask = proTaskMap.get(assignTask.getTaskId());
                if (proTask == null)
                    continue;
                ProTaskDetail proTaskDetail = proTaskDetailMap.get(assignTask.getTaskDetailId());
                if (proTaskDetail == null)
                    continue;
                TradeOrderDetail tradeOrderDetail = orderDetailMap.get(proTaskDetail.getTradeOrderDetailId());
                if (tradeOrderDetail == null)
                    continue;

                // 时间筛选
                if (StringUtils.isNotBlank(param.getFinishTime())) {
                    String completeDate = DateUtil.formatDateToString(assignTask.getCompleteTime(), DateUtil.DATE_FORMAT);
                    if (completeDate.compareTo(param.getFinishTime()) < 0)
                        continue;
                }

                // 搜索条件筛选
                if (StringUtils.isNotBlank(param.getSearch()))
                    if (!proTask.getCode().contains(param.getSearch()) && !tradeOrderDetail.getStyleCode().contains(param.getSearch()))
                        continue;

                CompleteTaskDto build = CompleteTaskDto.builder()
                        .assignTaskId(assignTask.getId())
                        .proTaskDetailId(assignTask.getTaskDetailId())
                        .proTaskCode(proTask.getCode())
                        .assignQty(assignTask.getAssignQty())
                        .completeQty(assignTask.getCompleteQty())
                        .styleCode(tradeOrderDetail.getStyleCode())
                        .colorName(tradeOrderDetail.getColorName())
                        .needleCode(tradeOrderDetail.getNeedle())
                        .colorMain(tradeOrderDetail.getColorMain())
                        .size(tradeOrderDetail.getSize())
                        .finishTime(DateUtil.formatDateToString(assignTask.getCompleteTime(), DateUtil.DATE_FORMAT_2))
                        .assignTime(DateUtil.formatDateToString(assignTask.getBeginTime()))
                        .build();
                res.add(build);
            }
        }

        return BizResult.success(res);
    }

    /**
     * pad完成任务激活
     *
     * @param assignTaskId
     * @return
     */
    @Override
    public BizResult<?> activeTask(String assignTaskId) {
        AssignTask assignTask = assignTaskMapper.selectById(assignTaskId);
        if (assignTask == null)
            return BizResult.fail("派工任务不存在");

        ProTask proTask = proTaskMapper.selectById(assignTask.getTaskId());
        if (proTask == null)
            return BizResult.fail("生产单不存在");

        if (proTask.getIsFinish() == 1)
            return BizResult.fail("生产单已完成");

        assignTask.setTaskStatus(1);
        assignTask.setCompleteTime(null);
        assignTaskMapper.updateById(assignTask);
        return BizResult.success();
    }

    /**
     * pad获取报工信息
     *
     * @param stationId
     * @return
     */
    @Override
    public BizResult<List<ReportRecordDto>> reportRecord(String stationId, String proTaskDetailId) {
        List<ReportRecordDto> res = new ArrayList<>();
        List<ReportRecord> reportRecords = reportRecordMapper.selectList(
                new QueryWrapper<ReportRecord>()
                        .eq("station_id", stationId)
                        .eq("pro_task_detail_id", proTaskDetailId)
                        .orderByDesc("create_time")
        );

        if (reportRecords.size() > 0)
            res.addAll(reportRecords.stream()
                    .map(c -> ReportRecordDto.builder()
                            .reportRecordId(c.getId())
                            .assignTaskId(c.getAssignTaskId())
                            .bookJobId(c.getBookJobId())
                            .proBoxCode(c.getProBoxCode())
                            .styleCode(c.getStyleCode())
                            .colorMain(c.getColorMain())
                            .size(c.getSize())
                            .needle(c.getNeedle())
                            .realName(c.getRealName())
                            .userNo(c.getUserNo())
                            .bookJobQty(c.getBookJobQty())
                            .reportTime(DateUtil.formatDateToString(c.getCreateTime()))
                            .build())
                    .collect(Collectors.toList()));

        return BizResult.success(res);
    }

    /**
     * pad删除报工信息
     * @param reportRecordId
     * @return
     */
    @Transactional
    @Override
    public BizResult<?> removeRecord(String reportRecordId) {
        ReportRecord reportRecord = reportRecordMapper.selectById(reportRecordId);
        if (reportRecord == null)
            return BizResult.success();

        mesBookjobMapper.deleteById(reportRecord.getBookJobId());

        MesProBox proBox = proBoxMapper.selectOne(new QueryWrapper<MesProBox>().eq("Code", reportRecord.getProBoxCode()));
        if (proBox != null) {
            proBox.setCurrentQty(proBox.getCurrentQty().subtract(reportRecord.getBookJobQty()));
            proBoxMapper.updateById(proBox);
        }

        AssignTask assignTask = assignTaskMapper.selectById(reportRecord.getAssignTaskId());
        assignTask.setCompleteQty(assignTask.getCompleteQty().subtract(reportRecord.getBookJobQty()));
        assignTaskMapper.updateById(assignTask);

        return BizResult.success();
    }

}
